#include <stdlib.h>
#include <stdio.h>
#include <vector>
#include <algorithm>

using namespace std;

class Demographics    // create Demographics class
{
    public:
        int numMales;
        int numFemales;
        int numDominant;
        int numRecessive;
        int numBoth;
};

class Man    // class definition for each person
{
    public:
        int maleFemale;
        int generationNumber;
        int dominantRecessiveBoth;    // Dominant = 1; Recessive = 2; Both = 4
        int unmarriedMarried;

    public:
        vector<Man> &getMarried(vector<Man> &nextGen, Demographics &demoMain, int index, int genNum, int maxChildren, int *popCount1, int *popCount2, int genSize)
        {
            for (int index2=0;index2<genSize;index2++)
            {
                if (nextGen[index].unmarriedMarried == 1)
                {
                    break;
                }

                if (nextGen[index2].maleFemale != nextGen[index].maleFemale && nextGen[index2].unmarriedMarried == 0 && nextGen[index2].generationNumber == nextGen[index].generationNumber)
                {
                    nextGen[index].unmarriedMarried  = 1;
                    nextGen[index2].unmarriedMarried = 1;

                    int parentsTrait = nextGen[index].dominantRecessiveBoth + nextGen[index2].dominantRecessiveBoth;
                    int numChildren = rand()%maxChildren+1;

                    for (int index3=0;index3<numChildren;index3++)
                    {
                        *popCount1 = *popCount1 + 1;
                        *popCount2 = *popCount2 + 1;
                        nextGen.push_back(Man());
                        nextGen[nextGen.size()-1] = createChild(nextGen[nextGen.size()-1],parentsTrait,genNum);
                        demoMain = nextGen[nextGen.size()-1].refreshDemographics(demoMain,nextGen[nextGen.size()-1]);
                    }
                }
            }
            return nextGen;
        }

        Man &createChild(Man &nextGen, int parentTrait, int genNum)
        {
            int gender = rand()%10+1;
            int genTrait = rand()%16+1;

            nextGen.generationNumber = genNum;

            if (gender <= 5)
                nextGen.maleFemale = 0;
            else
                nextGen.maleFemale = 1;

            if (parentTrait == 2)        // RR + RR
                nextGen.dominantRecessiveBoth = 1;
            else if (parentTrait == 3)    // RR + rr
                nextGen.dominantRecessiveBoth = 4;
            else if (parentTrait == 4)    // rr + rr
                nextGen.dominantRecessiveBoth = 2;
            else if (parentTrait == 5)    // RR + Rr
            {
                if (genTrait < 9)
                    nextGen.dominantRecessiveBoth = 1;
                else
                    nextGen.dominantRecessiveBoth = 4;
            }
            else if (parentTrait == 6)    // Rr + rr
            {
                if (genTrait < 9)
                    nextGen.dominantRecessiveBoth = 4;
                else
                    nextGen.dominantRecessiveBoth = 2;
            }
            else                        // Rr + Rr
            {
                if (genTrait < 5)
                    nextGen.dominantRecessiveBoth = 1;
                else if (genTrait > 4 && genTrait < 13)
                    nextGen.dominantRecessiveBoth = 4;
                else
                    nextGen.dominantRecessiveBoth = 2;
            }
            return nextGen;
        }

        Demographics refreshDemographics(Demographics demoMain, Man nextGen)
        {
            if (nextGen.maleFemale == 0)
                demoMain.numMales++;
            else
                demoMain.numFemales++;
            if (nextGen.dominantRecessiveBoth == 1)
                demoMain.numDominant++;
            else if (nextGen.dominantRecessiveBoth == 2)
                demoMain.numRecessive++;
            else
                demoMain.numBoth++;
            return demoMain;
        }

        vector<Man> &destroy(vector<Man> &nextGen, FILE *output, double *numDisaster, double *numDeaths, int *popCount)
        {
            int kill = rand()%10+1;
            if(kill == 1){
                int casualties = rand()%nextGen.size()+1;
                int type       = rand()%30+1;
                random_shuffle(nextGen.begin(),nextGen.end());
                nextGen.erase(nextGen.begin(),nextGen.begin()+casualties);
                *numDisaster = *numDisaster + 1;
                *numDeaths = *numDeaths + casualties;
                *popCount = *popCount - casualties;
                if(type < 11)
                {
                    printf("\n\t\t[*] Natural disaster occured and %d people died.\n",casualties);
                    fprintf(output,"\n\t\t[*] Natural disaster occured and %d people died.\n",casualties);
                }
                else if(type > 10 && type < 21) 
                {
                    printf("\n\t\t[*] War broke out and %d people died.\n",casualties);
                    fprintf(output,"\n\t\t[*] War broke out and %d people died.\n",casualties);
                }
                else
                {
                    printf("\n\t\t[*] Pestilence struck the earth and %d people died.\n",casualties);
                    fprintf(output,"\n\t\t[*] Pestilence struck the earth and %d people died.\n",casualties);
                }
            }
            return nextGen;
        }
};

